﻿using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;
using System.Xml;
using SHomeWorkshop.LunarPresentation.Adorners;
using SHomeWorkshop.LunarPresentation.Interfaces;

namespace SHomeWorkshop.LunarPresentation.Expressions
{
    public class LeafPanel : SubPanel, ICollapsed
    {
        public LeafPanel(SubPanel rootPanel, SubPanel parentPanel,
            Editor editor, Expression parentExpression)
            : base(rootPanel, parentPanel, editor, parentExpression)
        {
            HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch;
            VerticalAlignment = System.Windows.VerticalAlignment.Stretch;

            this.chineseName = "叶面板";
            this.Margin = cMargin;

            this.mainBorder.BorderBrush = Brushes.Transparent;
            this.mainBorder.BorderThickness = defNoneBorderWidth;
            Canvas.SetZIndex(this, 10);

            leafAdorner = new LeafAdorner(this);
            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.mainBorder);
            adornerLayer.Add(leafAdorner);
        }

        private LeafAdorner leafAdorner;

        private static Thickness cMargin = new Thickness(4);

        /// <summary>
        /// 叶首面板为0层。
        /// </summary>
        public int Level
        {
            get
            {
                int i = 0;

                LeafPanel sLeaf = this.PreLevelLeaf;
                while (sLeaf != null)
                {
                    sLeaf = sLeaf.PreLevelLeaf;
                    i++;
                }

                return i;
            }
        }

        private string preLevelLeafExID;

        /// <summary>
        /// 应保持叶首面板的这个属性值为null。
        /// </summary>
        public string PreLevelLeafExID
        {
            get { return preLevelLeafExID; }

            set
            {
                preLevelLeafExID = value;
                if (value != null)
                {
                    this.XmlData.SetAttribute("PreLevelLeafExID", value);
                }
                else
                {
                    this.XmlData.SetAttribute("PreLevelLeafExID", "");
                }

                //令父树重排各子面板。
                RefreshParentTreeLayout();
            }
        }

        private int index = 0;

        /// <summary>
        /// 在同一级、同一上级叶的各叶间的索引。用以确定纵坐标。
        /// 
        /// 此索引的值应来自于“插入”新叶。
        /// 之后则应受制于：MoveUp、MoveDown、MoveToHome、MoveToEnd这四个方法。
        /// </summary>
        public int Index
        {
            get { return index; }
            set
            {
                if (index != value)
                {
                    index = value;
                    if (this.XmlData != null)
                    {
                        this.XmlData.SetAttribute("Index", value.ToString());
                    }

                    RefreshParentTreeLayout();
                }
            }
        }

        /// <summary>
        /// 将此叶在同级向上移动一个位置。
        /// </summary>
        /// <returns></returns>
        public bool MoveUp()
        {
            return true;
        }

        /// <summary>
        /// 将此叶在同级向下移动一个位置。
        /// </summary>
        /// <returns></returns>
        public bool MoveDown()
        {
            return true;
        }

        /// <summary>
        /// 将此叶移动到同级最顶端。
        /// </summary>
        /// <returns></returns>
        public bool MoveToHome()
        {
            return true;
        }

        /// <summary>
        /// 将此叶移动到同级最底部。
        /// </summary>
        /// <returns></returns>
        public bool MoveToEnd()
        {
            return true;
        }

        /// <summary>
        /// 上级叶面板。
        /// </summary>
        public LeafPanel PreLevelLeaf
        {
            get
            {
                if (this.preLevelLeafExID == null || this.preLevelLeafExID == "") return null;

                if (this.ParentExpression == null) return null;

                Tree parentTree = this.ParentExpression as Tree;
                if (parentTree == null) return null;

                if (parentTree.Children == null ||
                    parentTree.Children.Count <= 0) return null;

                for (int i = 0; i < parentTree.Children.Count; i++)
                {
                    LeafPanel leaf = parentTree.Children[i] as LeafPanel;
                    if (leaf != null && leaf.ExID == this.preLevelLeafExID)
                    {
                        return leaf;
                    }
                }

                return null;
            }
        }

        private List<LeafPanel> nextLevelLeaves = new List<LeafPanel>();

        /// <summary>
        /// 下级面板列表。
        /// </summary>
        public List<LeafPanel> NextLevelLeaves
        {
            get { return nextLevelLeaves; }
            set { nextLevelLeaves = value; }
        }

        // 重载“上、下、左、右”四个属性。
        public override SubPanel LeftSubPanel
        {
            get
            {
                switch (this.leafType)
                {
                    case LeafPanelType.Root:
                        {
                            if (this.NextLevelLeaves.Count <= 0) return null;

                            for (int i = 0; i < this.NextLevelLeaves.Count; i++)
                            {
                                if (this.NextLevelLeaves[i].leafType == LeafPanelType.Left)
                                {
                                    //第一个向左的叶。
                                    return this.NextLevelLeaves[i];
                                }
                            }

                            return null;
                        }
                    case LeafPanelType.Left:
                        {
                            if (this.NextLevelLeaves.Count <= 0 || this.IsCollapsed) return null;

                            return this.NextLevelLeaves[0];
                        }
                    case LeafPanelType.Right:
                        {
                            return this.PreLevelLeaf;
                        }
                }

                return null;
            }
        }

        public override SubPanel RightSubPanel
        {
            get
            {
                switch (this.leafType)
                {
                    case LeafPanelType.Root:
                        {
                            if (this.NextLevelLeaves.Count <= 0) return null;

                            for (int i = 0; i < this.NextLevelLeaves.Count; i++)
                            {
                                if (this.NextLevelLeaves[i].leafType == LeafPanelType.Right)
                                {
                                    //第一个向右的叶。
                                    return this.NextLevelLeaves[i];
                                }
                            }

                            return null;
                        }
                    case LeafPanelType.Left:
                        {
                            return this.PreLevelLeaf;
                        }
                    case LeafPanelType.Right:
                        {
                            if (this.NextLevelLeaves.Count <= 0 || this.IsCollapsed) return null;

                            return this.NextLevelLeaves[0];
                        }
                }

                return null;
            }
        }

        public override SubPanel TopSubPanel
        {
            get
            {
                if (this.ParentExpression == null) return null;
                if (this.ParentExpression is Expressions.Tree == false) return null;

                LeafPanel preLevelLeaf = this.PreLevelLeaf;
                if (preLevelLeaf == null) return null;

                if (preLevelLeaf.leafType == LeafPanelType.Root)
                {
                    if (index > 0 && index < preLevelLeaf.NextLevelLeaves.Count)
                    {
                        for (int i = index - 1; i >= 0; i--)
                        {
                            if (preLevelLeaf.NextLevelLeaves[i].leafType ==
                                this.leafType)
                            {
                                return preLevelLeaf.NextLevelLeaves[i];
                            }
                        }

                        return preLevelLeaf;
                    }
                    else return preLevelLeaf;
                }
                else
                {
                    int preIndex = this.index - 1;
                    if (preIndex >= 0 && preIndex < preLevelLeaf.NextLevelLeaves.Count)
                    {
                        return preLevelLeaf.NextLevelLeaves[preIndex];
                    }
                    else
                    {
                        return preLevelLeaf;
                    }
                }
            }
        }

        public void LoadPreLevelExID()
        {
            XmlAttribute attrPreLevelLeafExid = this.XmlData.GetAttribute("PreLevelLeafExID");
            if (attrPreLevelLeafExid != null)
            {
                this.preLevelLeafExID = attrPreLevelLeafExid.Value;
            }
        }

        public override SubPanel BottomSubPanel
        {
            get
            {
                if (this.ParentExpression == null) return null;
                if (this.ParentExpression is Expressions.Tree == false) return null;

                LeafPanel preLevelLeaf = this.PreLevelLeaf;
                if (preLevelLeaf == null) return null;

                if (preLevelLeaf.leafType == LeafPanelType.Root)
                {
                    if (index >= 0 && index < preLevelLeaf.NextLevelLeaves.Count - 1)
                    {
                        for (int i = index + 1; i < preLevelLeaf.NextLevelLeaves.Count; i++)
                        {
                            if (preLevelLeaf.NextLevelLeaves[i].leafType ==
                                this.leafType)
                            {
                                return preLevelLeaf.NextLevelLeaves[i];
                            }
                        }

                        return preLevelLeaf;
                    }
                    else return preLevelLeaf;
                }
                else
                {
                    int nextIndex = this.index + 1;
                    if (nextIndex >= 0 && nextIndex < preLevelLeaf.NextLevelLeaves.Count)
                    {
                        return preLevelLeaf.NextLevelLeaves[nextIndex];
                    }
                    else
                    {
                        return preLevelLeaf;
                    }
                }
            }
        }

        /// <summary>
        /// 叶面板的类型。Root为树的“中心标题”所专用。
        /// 一个树中只应该有一个。
        /// </summary>
        public enum LeafPanelType { Left, Right, Root }

        private LeafPanelType leafType = LeafPanelType.Right;

        public LeafPanelType LeafType
        {
            get { return leafType; }
            set
            {
                leafType = value;
                if (this.XmlData != null)
                {
                    this.XmlData.SetAttribute
                        ("LeafType", leafType.ToString());
                }

                RefreshChineseName();
            }
        }

        private void RefreshChineseName()
        {
            switch (leafType)
            {
                case LeafPanelType.Root:
                    {
                        chineseName = "叶首面板"; break;
                    }
                default:
                    {
                        chineseName = "叶面板"; break;
                    }
            }
        }

        /// <summary>
        /// 用以临时记录布局时需要的尺寸。
        /// 此值由树临时产生，临时使用。平时不应使用。
        /// </summary>
        public Size NeedSize { get; set; }

        public static readonly Thickness defBorderWidth = new Thickness(2);

        public static readonly Thickness defNoneBorderWidth = new Thickness(0);

        public override void UpdateExForegroundWithoutXmlChanging(Brush value)
        {
            base.UpdateExForegroundWithoutXmlChanging(value);

            if (this.XmlData != null)
            {
                if (this.LeafType == LeafPanelType.Root)
                {
                    XmlAttribute attrBorderColor = this.XmlData.GetAttribute("BorderColor");
                    if (attrBorderColor == null)
                    {
                        this.mainBorder.BorderBrush = this.ExForeground;
                    }

                    XmlAttribute attrBorderWidth = this.XmlData.GetAttribute("BorderWidth");
                    if (attrBorderWidth == null)
                    {
                        this.mainBorder.BorderThickness = defBorderWidth;
                    }
                }
                else
                {
                    XmlAttribute attrBorderColor = this.XmlData.GetAttribute("BorderColor");
                    if (attrBorderColor == null)
                    {
                        this.mainBorder.BorderBrush = Brushes.Transparent;
                    }

                    XmlAttribute attrBorderWidth = this.XmlData.GetAttribute("BorderWidth");
                    if (attrBorderWidth == null)
                    {
                        this.mainBorder.BorderThickness = defNoneBorderWidth;
                    }
                }
            }
        }

        protected override void BuildChildren()
        {
            base.BuildChildren();

            if (this.XmlData == null) return;

            try
            {
                XmlAttribute attrLeafType = this.XmlData.GetAttribute("LeafType");
                if (attrLeafType != null)
                {
                    this.leafType = (LeafPanelType)Enum.Parse(typeof(LeafPanelType), attrLeafType.Value);
                }

                RefreshChineseName();

                XmlAttribute attrIndex = this.XmlData.GetAttribute("Index");
                if (attrIndex != null)
                {
                    this.index = int.Parse(attrIndex.Value);
                }

                XmlAttribute attrPreLevelLeafExID = this.XmlData.GetAttribute("PreLevelLeafExID");
                if (attrPreLevelLeafExID != null && attrPreLevelLeafExID.Value != "")
                {
                    this.preLevelLeafExID = attrPreLevelLeafExID.Value;
                }

                XmlAttribute attrBorderColor = this.XmlData.GetAttribute("BorderColor");
                if (attrBorderColor == null && this.Editor != null)
                {
                    this.mainBorder.BorderBrush = this.Editor.DefaultForeground;
                }

                XmlAttribute attrIsCollapsed = this.XmlData.GetAttribute("IsCollapsed");
                if (attrIsCollapsed != null)
                {
                    this.isCollapsed = bool.Parse(attrIsCollapsed.Value);
                    RefreshParentTreeLayout();
                }

                UpdateExForegroundWithoutXmlChanging(this.exForeground);
            }
            catch (Exception ex)
            {
                Dialogs.LunarMsgBox.MsgBoxShow(
                    Globals.appName,
                    "发生意外错误，叶子面板未能顺利生成！",
                    "异常信息如下：\r\n" + ex.Message,
                    ex.StackTrace, MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }
        }

        public override void SetProperty(string propertyName, string value)
        {
            base.SetProperty(propertyName, value);

            switch (propertyName)
            {
                case "LeafType":
                    {
                        this.LeafType = (LeafPanelType)Enum.Parse(typeof(LeafPanelType), value);
                        break;
                    }
                case "Index":
                    {
                        this.Index = int.Parse(value);
                        break;
                    }
                case "PreLevelLeafExID":
                    {
                        this.PreLevelLeafExID = value;
                        break;
                    }
                case "IsCollapsed":
                    {
                        this.IsCollapsed = bool.Parse(value);
                        break;
                    }
            }
        }

        /// <summary>
        /// 此方法应递归调用，用以取出一个叶面板的所有“下级”及其自身的OutXml文本。
        /// List中最后一个就是leaf的OutXml文本。结果是逆序存放的。
        /// </summary>
        /// <param name="leaf"></param>
        /// <param name="xmlTextList"></param>
        public static void GetOutXmls(LeafPanel leaf, List<string> xmlTextList)
        {
            if (leaf == null || xmlTextList == null) return;

            List<LeafPanel> nextLevelLeafs = leaf.NextLevelLeaves;
            if (nextLevelLeafs != null)
            {
                foreach (LeafPanel lp in nextLevelLeafs)
                {
                    GetOutXmls(lp, xmlTextList);
                }
            }

            //最后是自身。
            if (leaf.XmlData != null)
            {
                xmlTextList.Add(leaf.XmlData.OuterXml);
            }
        }

        private bool isCollapsed = false;

        public bool IsCollapsed
        {
            get
            {
                return isCollapsed;
            }
            set
            {
                isCollapsed = value;
                this.XmlData.SetAttribute("IsCollapsed", value.ToString());

                this.leafAdorner.InvalidateVisual();

                RefreshParentTreeLayout();
            }
        }

        private void RefreshParentTreeLayout()
        {
            if (this.ParentExpression != null)
            {
                Expressions.Tree pTree = this.ParentExpression as Expressions.Tree;
                if (pTree != null)
                {
                    pTree.RefreshLayout();
                }
            }
        }

        public void ReloadPreLevelLeafExIDFromXmlData()
        {
            if (this.XmlData == null) return;

            XmlAttribute attrPreLevelLeafExID = this.XmlData.GetAttribute("PreLevelLeafExID");
            if (attrPreLevelLeafExID != null)
            {
                this.preLevelLeafExID = attrPreLevelLeafExID.Value;
            }
        }

        /// <summary>
        /// 如果当前叶的高度比它的所有下级叶需要的总高度还高，则此值应大于０。
        /// 此值是高出的部分的一半。
        /// </summary>
        public double SurplusHalfHeight { get; set; }
    }

    class LeafIndexCompare : IComparer<LeafPanel>
    {
        public int Compare(LeafPanel x, LeafPanel y)
        {
            if (x.Index == y.Index) return 0;
            else return x.Index > y.Index ? 1 : -1;
        }
    }
}
